Passed
Push — master ( 693395...3643fc )
by Dev
03:15
created

helpers.js ➔ liveBlock   B

Complexity

Conditions 8

Size

Total Lines 35
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 19
dl 0
loc 35
rs 7.3333
c 0
b 0
f 0
1
/**
2
 * List of all functions
3
 *
4
 * - liveBlock(attr)
5
 * - liveForm(attr)
6
 *
7
 * - responsiveImage(string)    Relative to Liip filters
8
 * - uncloakLinks(attr)
9
 * - convertFormFromRot13(attr)
10
 * - readableEmail(attr)
11
 * - convertImageLinkToWebPLink()
12
 */
13
14
/**
15
 * Live Block Watcher (and button)
16
 * 
17
 * Fetch (ajax) function permitting to get block via a POST request
18
 *
19
 * @param {string} attribute
20
 */
21
export function liveBlock(attribute = "data-live") {
22
    
23
  var btnToBlock = function(event, btn) {
24
    btn.setAttribute(attribute, btn.getAttribute("src-"+attribute));
25
    getLiveBlock(btn);    
26
  }
27
  
28
  var getLiveBlock = function(item) {
29
    fetch(item.getAttribute(attribute), {
30
      //headers: { "Content-Type": "application/json", Accept: "text/plain" },
31
      method: "POST",
32
      credentials: "include"
33
    })
34
    .then(function(response) {
35
      return response.text();
36
    })
37
    .then(function(body) {
38
      item.removeAttribute(attribute);
39
      item.outerHTML = body;
40
41
      document.dispatchEvent(new Event("DOMChanged"));
0 ignored issues
show
Bug introduced by
The variable Event seems to be never declared. If this is a global, consider adding a /** global: Event */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
42
    });
43
  }
44
  
45
  document.querySelectorAll("[" + attribute + "]").forEach(item => {
46
    getLiveBlock(item);
47
  });
48
  
49
  document.querySelectorAll("[src-" + attribute + "]").forEach(item => {
50
    item.addEventListener("click", event => {
51
      btnToBlock(event, item);
52
    });
53
  });
54
  
55
}
56
57
/**
58
 * ajaxify-form
59
 */
60
export function liveForm(selector = '.live-form') {
61
  document.querySelectorAll(selector).forEach(item => {
62
    if (item.querySelector("form") !== null) {
63
      item.querySelector("form").addEventListener("submit", e => {
64
        e.preventDefault();
65
        sendForm(e, item);
66
      });
67
    }
68
  });
69
70
  var setLoader = function (form) {
71
    var $submitButton = getSubmitButton(form);
72
    if ($submitButton !== undefined) {
73
      var initialButton = $submitButton.outerHTML;
0 ignored issues
show
Unused Code introduced by
The variable initialButton seems to be never used. Consider removing it.
Loading history...
74
      $submitButton.innerHTML = '';
75
      $submitButton.outerHTML = '<div style="width:1em;height:1em;border: 2px solid #222;border-top-color: #fff;border-radius: 50%;  animation: 1s spin linear infinite;"></div><style>@keyframes spin {from{transform:rotate(0deg)}to{transform:rotate(360deg)}}</style>';
76
    }
77
  }
78
  
79
  var sendForm = function(form, liveFormBlock) {
80
     setLoader(form);
81
     
82
    var formData = new FormData(form.srcElement);
83
    fetch(form.srcElement.action, {
84
      method: "POST",
85
      body: formData,
86
      credentials: "include"
87
    })
88
      .then(function(response) {
89
        return response.text();
90
      })
91
      .then(function(body) {
92
        liveFormBlock.outerHTML = body;
93
      })
94
      .then(function() {
95
        document.dispatchEvent(new Event("DOMChanged"));
0 ignored issues
show
Bug introduced by
The variable Event seems to be never declared. If this is a global, consider adding a /** global: Event */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
96
      });
97
  };
98
99
  var getSubmitButton = function(form) {
100
    if (form.srcElement.querySelector("[type=submit]") !== null) {
101
      return form.srcElement.querySelector("[type=submit]");
102
    }
103
    if (form.srcElement.getElementsByTagName("button") !== null) {
104
      return form.srcElement.getElementsByTagName("button")[0];
105
    }
106
    return null;
107
  };
108
}
109
110
/**
111
 * Transform image's path (src) produce with Liip to responsive path
112
 *
113
 * @param {string} src
114
 */
115
export function responsiveImage(src) {
116
  var screenWidth = window.innerWidth;
117
  if (screenWidth <= 576) {
118
    src = src.replace("/default/", "/xs/");
119
  } else if (screenWidth <= 768) {
120
    src = src.replace("/default/", "/sm/");
121
  } else if (screenWidth <= 992) {
122
    src = src.replace("/default/", "/md/");
123
  } else if (screenWidth <= 1200) {
124
    src = src.replace("/default/", "/lg/");
125
  } else {
126
    // 1200+
127
    src = src.replace("/default/", "/xl/");
128
  }
129
130
  return src;
131
}
132
133
/**
134
 * Convert elements wich contain attribute (data-href) in normal link (a href)
135
 * You can use a callback function to decrypt the link (eg: rot13ToText ;-))
136
 *
137
 * @param {string}  attribute
138
 */
139
export async function uncloakLinks(attribute = "data-rot") {
140
  var convertLink = function(element) {
141
    // fix "bug" with img
142
    if (element.getAttribute(attribute) === null) {
143
      var element = element.closest("[" + attribute + "]");
144
    }
145
    if (element.getAttribute(attribute) === null) return;
0 ignored issues
show
Comprehensibility Best Practice introduced by
Are you sure this return statement is not missing an argument? If this is intended, consider adding an explicit undefined like return undefined;.
Loading history...
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
146
    var link = document.createElement("a");
147
    var href = element.getAttribute(attribute);
148
    element.removeAttribute(attribute);
149
    for (var i = 0, n = element.attributes.length; i < n; i++) {
150
      link.setAttribute(
151
        element.attributes[i].nodeName,
152
        element.attributes[i].nodeValue
153
      );
154
    }
155
    link.innerHTML = element.innerHTML;
156
    link.setAttribute(
157
      "href",
158
      responsiveImage(convertShortchutForLink(rot13ToText(href)))
159
    );
160
    element.parentNode.replaceChild(link, element);
161
    return link;
162
  };
163
164
  var convertThemAll = function(attribute) {
165
    [].forEach.call(document.querySelectorAll("[" + attribute + "]"), function(
166
      element
167
    ) {
168
      convertLink(element);
169
    });
170
  };
171
172
  var fireEventLinksBuilt = async function(element, event) {
173
    await document.dispatchEvent(new Event("DOMChanged"));
0 ignored issues
show
Bug introduced by
The variable Event seems to be never declared. If this is a global, consider adding a /** global: Event */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
174
175
    var clickEvent = new Event(event.type);
176
    element.dispatchEvent(clickEvent);
177
  };
178
179
  var convertLinkOnEvent = async function(event) {
180
    // convert them all if it's an image (thanks this bug), permit to use gallery (baguetteBox)
181
    if (event.target.tagName == "IMG") {
182
      await convertThemAll(attribute);
183
      var element = event.target;
184
    } else {
185
      var element = convertLink(event.target);
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable element already seems to be declared on line 183. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
186
    }
187
    fireEventLinksBuilt(element, event);
188
  };
189
190
  [].forEach.call(document.querySelectorAll("[" + attribute + "]"), function(
191
    element
192
  ) {
193
    element.addEventListener(
194
      "touchstart",
195
      function(e) {
196
        convertLinkOnEvent(e);
197
      },
198
      { once: true }
199
    );
200
    element.addEventListener(
201
      "click",
202
      function(e) {
203
        convertLinkOnEvent(e);
204
      },
205
      { once: true }
206
    );
207
    element.addEventListener(
208
      "mouseover",
209
      function(e) {
210
        convertLinkOnEvent(e);
211
      },
212
      { once: true }
213
    );
214
  });
215
}
216
217
/**
218
 * Convert action attr encoded in rot 13 to normal action with default attr `data-frot`
219
 *
220
 * @param {string}  attribute
221
 */
222
export function convertFormFromRot13(attribute = "data-frot") {
223
  [].forEach.call(document.querySelectorAll("[" + attribute + "]"), function(
224
    element
225
  ) {
226
    var action = element.getAttribute(attribute);
227
    element.removeAttribute(attribute);
228
    element.setAttribute(
229
      "action",
230
      convertShortchutForLink(rot13ToText(action))
231
    );
232
  });
233
}
234
235
export function convertShortchutForLink(str) {
236
  if (str.charAt(0) == "-") {
237
    return str.replace("-", "http://");
238
  }
239
  if (str.charAt(0) == "_") {
240
    return str.replace("_", "https://");
241
  }
242
  if (str.charAt(0) == "@") {
243
    return str.replace("@", "mailto:");
244
  }
245
  return str;
246
}
247
248
/**
249
 * readableEmail(selector) Transform an email encoded with rot13 in a readable mail (and add mailto:)
250
 *
251
 * @param {string}  text
252
 */
253
export function readableEmail(selector) {
254
  document.querySelectorAll(selector).forEach(function(item) {
255
    var mail = rot13ToText(item.textContent);
256
    item.innerHTML = '<a href="mailto:' + mail + '">' + mail + "</a>";
257
    if (selector.charAt(0) == ".") {
258
      item.classList.remove(selector.substring(1));
259
    }
260
  });
261
}
262
263
/**
264
 * Decode rot13
265
 *
266
 * @param {string}  str
267
 */
268
export function rot13ToText(str) {
269
  return str.replace(/[a-zA-Z]/g, function(c) {
270
    return String.fromCharCode(
271
      (c <= "Z" ? 90 : 122) >= (c = c.charCodeAt(0) + 13) ? c : c - 26
272
    );
273
  });
274
}
275
276
export function testWebPSupport() {
277
  var elem = document.createElement("canvas");
278
279
  if (elem.getContext && elem.getContext("2d")) {
280
    return elem.toDataURL("image/webp").indexOf("data:image/webp") == 0;
0 ignored issues
show
Best Practice introduced by
Comparing elem.toDataURL("image/we...exOf("data:image/webp") to 0 using the == operator is not safe. Consider using === instead.
Loading history...
281
  }
282
283
  return false;
284
}
285
286
/**
287
 * Used in ThemeComponent
288
 */
289
export function convertImageLinkToWebPLink() {
290
  var switchToWebP = function() {
291
    [].forEach.call(document.querySelectorAll("a[dwl]"), function(element) {
292
      var href = responsiveImage(element.getAttribute("dwl"));
293
      element.setAttribute("href", href);
294
      element.removeAttribute("dwl");
295
    });
296
  };
297
298
  if (testWebPSupport()) switchToWebP();
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
299
}
300
301
/**
302
 * Simple Image Lazy Loader
303
 * original from : https://davidwalsh.name/lazyload-image-fade
304
 *
305
 * @param {string}  attribute
306
 *
307
 * @example
308
 * imgLazyLoad()
309
 * <span data-img=/img/me.png>Tagada</span> or <img data-img=/img/me.png alt=Tagada>
310
 *
311
 * will be converted to
312
 *
313
 * <img src=/img/me.png alt=Tagada />
314
 * 
315
 * still used in piedvert. To remove ?!
316
 */
317
export function imgLazyLoad(attribute = "data-img") {
318
  [].forEach.call(document.querySelectorAll("[" + attribute + "]"), function(
319
    img
320
  ) {
321
    var newDomImg = document.createElement("img");
322
    var src = img.getAttribute(attribute);
323
    img.removeAttribute(attribute);
324
    for (var i = 0, n = img.attributes.length; i < n; i++) {
325
      newDomImg.setAttribute(
326
        img.attributes[i].nodeName,
327
        img.attributes[i].nodeValue
328
      );
329
    }
330
    if (newDomImg.getAttribute("alt") === null && img.textContent != "") {
331
      newDomImg.setAttribute("alt", img.textContent);
332
    }
333
    newDomImg.setAttribute(
334
      "src",
335
      typeof responsiveImage === "function" ? responsiveImage(src) : src
336
    );
337
    img.outerHTML = newDomImg.outerHTML;
338
  });
339
}
340